/**
 * 
 */
package de.cbf.cam.dsa.tavern.carte.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;

import de.cbf.cam.dsa.tavern.carte.exceptions.WrongTypeProvidedException;
import de.cbf.cam.dsa.tavern.carte.model.entities.Ingredient;
import de.cbf.cam.dsa.tavern.carte.model.entities.MealType;
import de.cbf.cam.dsa.tavern.carte.model.entities.helper.MinMax;
import de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.IEditableEntity;
import de.cbf.cam.dsa.tavern.carte.ui.CompositeEditMealType;
import de.cbf.cam.dsa.tavern.carte.ui.interfaces.ICompositeEditEntity;

/**
 * @author Stefan Alter
 *
 */
public class ControllerEditMealType extends ControllerEditEntity {
	private Iterator<Ingredient> 	iteratorRootIngredients;
	/**
	 * 
	 */
	public ControllerEditMealType() {		
	}

	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.controller.ControllerEditEntity#checkEntity(de.cbf.cam.dsa.tavern.carte.model.entities.interfaces.IEditableEntity)
	 */
	@Override
	protected boolean checkEntity(IEditableEntity value)
			throws IllegalArgumentException {
		if (value instanceof MealType) {
			return true;			
		}
		if(value == null){
			throw new WrongTypeProvidedException(MealType.class.getName(),"null");	
		}
		throw new WrongTypeProvidedException(MealType.class, value.getClass());
	}

	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.controller.ControllerEditEntity#checkView(de.cbf.cam.dsa.tavern.carte.ui.interfaces.ICompositeEditEntity)
	 */
	@Override
	protected boolean checkView(ICompositeEditEntity value)
			throws IllegalArgumentException {
		if (value instanceof CompositeEditMealType) {			
			return true;
		}
		if(value == null){
			throw new WrongTypeProvidedException(CompositeEditMealType.class.getName(),"null");	
		}
		throw new WrongTypeProvidedException(CompositeEditMealType.class, value.getClass());	
	}

	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.controller.ControllerEditEntity#registerViewListenersAndInit(de.cbf.cam.dsa.tavern.carte.ui.interfaces.ICompositeEditEntity)
	 */
	@Override
	protected boolean registerViewListenersAndInit(ICompositeEditEntity value) {
		if (value instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) value;
			//register view listeners
			composite.registerIngredientSelectionListener			(ingredientSelection);			
			composite.registerNameModifyListener					(nameModify);
			composite.registerPriceModifyListener					(priceModify);			
			composite.registerConfigurationElementSelectionListener	(configurationElementSelected);
			composite.registerModifyConfigurationListener			(configurationModify);
			composite.registerAddIngredientListener					(addIngredient);
			composite.registerRemoveIngredientListener				(removeIngredient);			
			//init view
			if(iteratorRootIngredients != null){
				//if we have a not yet applied iterator for root ingredients, we apply it
				composite.setIngredients(iteratorRootIngredients);
			}
			return true;
		}else{
			return false;
		}		
	}

	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.controller.ControllerEditEntity#deRegisterViewListeners(de.cbf.cam.dsa.tavern.carte.ui.interfaces.ICompositeEditEntity)
	 */
	@Override
	protected boolean deRegisterViewListeners(ICompositeEditEntity value) {
		if (value instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) value;
			composite.deRegisterIngredientSelectionListener				(ingredientSelection);			
			composite.deRegisterNameModifyListener						(nameModify);
			composite.deRegisterPriceModifyListener						(priceModify);			
			composite.deRegisterConfigurationElementSelectionListener	(configurationElementSelected);
			composite.deRegisterModifyConfigurationListener				(configurationModify);
			composite.deRegisterAddIngredientListener					(addIngredient);
			composite.deRegisterRemoveIngredientListener				(removeIngredient);					
			return true;
		}else{
			return false;
		}		
	}
	/* (non-Javadoc)
	 * @see de.cbf.cam.dsa.tavern.carte.controller.ControllerEditEntity#getPCLforEntity()
	 */
	@Override
	protected PropertyChangeListener getPCLforEntity() {
		return pclMealType;
	}
	private final PropertyChangeListener pclMealType = new PCLMealType();
	private class PCLMealType implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if (view instanceof CompositeEditMealType) {
				CompositeEditMealType composite = (CompositeEditMealType) view;
				if (evt instanceof IndexedPropertyChangeEvent) {					
//					IndexedPropertyChangeEvent idxEvent = (IndexedPropertyChangeEvent) evt;	
					//TODO fineGrain property update
					composite.setEntity(entity);
//					view.setMealTypeName(mealType.getName());
//					view.setPrice(mealType.getPrice());
//					view.setConfiguration(mealType.getConfigProbabilityMap());	
				}else{
					//brutal update, because we do not know which property changed
					composite.setEntity(entity);
				}
			}
				
		}		
	}
	
	public void setIngredients(Iterator<Ingredient> iteratorRootIngredients) {
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;
			composite.setIngredients(iteratorRootIngredients);
		}else{
			//if view is not yet active save the iterator of the root ingredients for later adding of ingredients
			this.iteratorRootIngredients = iteratorRootIngredients;
		}
	}	
	
	public void doIngredientSelection(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;
			Ingredient ingredient = composite.getSelectedTreeIngredient();
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				if(mealType.getConfigProbabilityMap().containsKey(ingredient.getName())){
					composite.setButtonAddEnabled(false);
				}else{
					composite.setButtonAddEnabled(true);
				}		
				composite.setButtonAddEnabled(true);
			}			
		}		
	}
	
	
	public void doNameModify(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				mealType.setName(composite.getMealTypeName());
				testUnsavedChanges();
			}				
		}
	}
	
	public void doPriceModify(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				mealType.setPrice(composite.getPrice());
				testUnsavedChanges();
			}				
		}
	}
	
	public void doConfigurationModify(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;			
			String ingredientName 			 = composite.getSelectedIngredientName();
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				MinMax probability   = mealType.getConfigProbabilityMap().get(ingredientName);
				if(probability == null){
					probability = new MinMax(); // new ingredient added 
				}			
				probability.setMin(composite.getSelectedMin());
				probability.setMax(composite.getSelectedMax());			
				if(ingredientName != null){
					mealType.putModifyConfigEntry(ingredientName, probability);
					testUnsavedChanges();
				}
			}
		}			
	}
	
	public void doConfigurationElementSelect(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;				
			if(composite.getSelectedIngredientName()!= null){
				composite.setButtonRemoveEnabled(true);
			}
		}
	}
	
	public void doAddIngredient(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;		
			composite.setButtonAddEnabled(false);
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				Ingredient ingredient = composite.getSelectedTreeIngredient();			
				mealType.putModifyConfigEntry(ingredient.getName(),new MinMax());			
				composite.deSelectAllTreeIngredients();
				testUnsavedChanges();
			}
		}	
	}
	
	public void doRemoveIngredient(){
		if (view instanceof CompositeEditMealType) {
			CompositeEditMealType composite = (CompositeEditMealType) view;				
			composite.setButtonRemoveEnabled(false);
			if (entity instanceof MealType) {
				MealType mealType = (MealType) entity;
				String ingredientName = composite.getSelectedIngredientName();			
				mealType.removeConfigEntry(ingredientName);			
				testUnsavedChanges();
			}
		}
	}
	
	private IngredientSelection ingredientSelection = new IngredientSelection();	
	private class IngredientSelection implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doIngredientSelection();
		}		
	}
	
	private NameModify nameModify = new NameModify();	
	private class NameModify implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doNameModify();
		}		
	}
	private PriceModify priceModify = new PriceModify();	
	private class PriceModify implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doPriceModify();
		}		
	}	
	
	private ConfigurationModify configurationModify = new ConfigurationModify();	
	private class ConfigurationModify implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doConfigurationModify();
		}		
	}
	private ConfigurationElementSelected configurationElementSelected = new ConfigurationElementSelected();	
	private class ConfigurationElementSelected implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doConfigurationElementSelect(); 
		}		
	}	
	
	
	private AddIngredient addIngredient = new AddIngredient();	
	private class AddIngredient implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doAddIngredient();		
		}		
	}
	private RemoveIngredient removeIngredient = new RemoveIngredient();	
	private class RemoveIngredient implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			doRemoveIngredient();
		}		
	}
	
	
	
	
	
	

}
